package sk.upjs.ariadne.editor;

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.geom.*;

import javax.swing.JPanel;

/**
 * Base class for implementing map layers that can be displayed by MapPanel.
 */
public abstract class MapLayer {

	/**
	 * The parent of the map layer - a map panel that displays this layer.
	 */
	private MapPanel parent;

	/**
	 * Indicates whether this layer is currently edited.
	 */
	private boolean edited;

	/**
	 * Returns the parent of this map layer - a map panel that displays this
	 * layer.
	 * 
	 * @return a map panel that serves as a container for this map layer.
	 */
	public MapPanel getParent() {
		return parent;
	}

	/**
	 * Sets the parent of this map layer. This method is called by a map panel,
	 * when the layer is added to or removed from a map panel.
	 * 
	 * @param parent
	 *            the new parent of this layer.
	 */
	void setParent(MapPanel parent) {
		this.parent = parent;
	}

	/**
	 * Initiates the edit mode for this map layer. This method is called by a
	 * map panel that contains this map layer.
	 */
	void startLayerEditing() {
		if (edited)
			return;

		edited = true;
		onEditStart();
	}

	/**
	 * Closes the edit mode for this map layer. This method is called by a map
	 * panel that contains this map layer.
	 */
	void stopLayerEditing() {
		if (!edited)
			return;

		edited = false;
		onEditFinish();
	}

	/**
	 * Returns whether this layer is currently edited.
	 * 
	 * @return true, if the layer is edited, false otherwise.
	 */
	public boolean isEdited() {
		return edited;
	}

	/**
	 * Returns the current zoom of the parent map panel.
	 * 
	 * @return the current zoom of the parent map panel, or Double.NaN when the
	 *         layer is contained in a map panel.
	 */
	public double getParentZoom() {
		if (parent != null)
			return parent.getZoom();
		else
			return Double.NaN;
	}

	/**
	 * Requests the parent map panel to repaint this map layer. This method
	 * should be called whenever the view of the map layer has been changed in
	 * order to update the view.
	 */
	protected void repaint() {
		if (parent != null)
			parent.forceRepaintByLayer(this);
	}

	/**
	 * Returns a minimal bounding rectangle that contains all elements of this
	 * map layer.
	 * 
	 * @return a bounding rectangle of all layer elements.
	 */
	public Rectangle2D getBoundingRect() {
		return null;
	}

	/**
	 * Returns a JPanel with edit controls for editing and managing content of
	 * this layer.
	 * 
	 * @return a JPanel containing edit controls for this map layer.
	 */
	public JPanel getControlPanel() {
		return null;
	}

	/**
	 * Returns the name of the layer that can be used to identify the layer for
	 * a user.
	 * 
	 * @return the name of the layer
	 */
	public String getLayerName() {
		return toString();
	}

	// ----------------------------------------------------------------------
	// Paint handling methods (painting handlers to override)
	// ----------------------------------------------------------------------

	/**
	 * Paints the map layer
	 * 
	 * @param g
	 */
	public void paint(Graphics2D g, Rectangle2D area) {
	}

	/**
	 * Paints the map layer
	 * 
	 * @param g
	 */
	public void paintEditOverlay(Graphics2D g, Rectangle2D area) {

	}

	// ----------------------------------------------------------------------
	// Mouse control methods (event handlers to override)
	// ----------------------------------------------------------------------

	protected void onMouseReleased(Point2D coordinates, MouseEvent e) {

	}

	protected void onMousePressed(Point2D coordinates, MouseEvent e) {

	}

	protected void onMouseExited(Point2D coordinates, MouseEvent e) {

	}

	protected void onMouseEntered(Point2D coordinates, MouseEvent e) {

	}

	protected void onMouseClicked(Point2D coordinates, MouseEvent e) {

	}

	protected void onMouseMoved(Point2D coordinates, MouseEvent e) {

	}

	protected void onMouseDragged(Point2D coordinates, MouseEvent e) {

	}

	// ----------------------------------------------------------------------
	// Edit control methods (event handlers to override)
	// ----------------------------------------------------------------------

	protected void onEditStart() {

	}

	protected void onEditFinish() {

	}

	protected void onZoomChanged(double zoom) {

	}
}
